package swing;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Vector;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

import commands.CommandInterface;

import devices.AbstractDevice;

import smarthouse.Smarthouse;
import swing.renderer.BooleanRenderer;
import swing.renderer.IntegerRenderer;
import swing.renderer.Renderer;
import swing.renderer.RendererFactory;
import swing.renderer.SliderRenderer;
import swing.renderer.StringRenderer;

import annotations.Command;
import annotations.Param;
import annotations.Reading;

public class CommandFrame extends JPanel implements ActionListener{
	
	AbstractDevice targetDevice;
	Class commandClass = null;
	Vector<Renderer> renderers = new Vector<Renderer>();
	CommandInterface command = null;
	
	public CommandFrame(Class<?> commandClass, AbstractDevice targetDevice){
		
		this.commandClass=commandClass;
		this.targetDevice=targetDevice;
		
		try {
			command = (CommandInterface) commandClass.getConstructors()[0].newInstance();
		} catch (Exception e1) {
			e1.printStackTrace();
		} 
		
		Command annotation = commandClass.getAnnotation(Command.class);
		Hashtable<Integer,Object> deviceData;
		//deviceData = Server.getInstance().getDeviceData(commandClass);
		deviceData = Smarthouse.getInstance().getDeviceData(targetDevice);
				
		String commandName = annotation.name();
		String commandDescription = annotation.description();
		String commandIconURL = annotation.iconURL();
		
		this.setLayout(new BorderLayout());
		JPanel paramsFrame = new JPanel();
		paramsFrame.setLayout(new GridLayout(commandClass.getDeclaredFields().length, 1));
		
		Field[] fields= commandClass.getDeclaredFields();
		Field field = null;
		
		JLabel label =new JLabel("<html><font size=+1>"+commandName+"</font></html>");
		label.setHorizontalAlignment(SwingConstants.CENTER);
		this.add(label,BorderLayout.NORTH);
		
		for (int i=0;i<fields.length;i++){
			field = fields[i];
			
			if (field.isAnnotationPresent(Param.class)){
				
				System.out.println(field.getName());
				Class<?> type = field.getType();
				System.out.println("\t"+field.getType());
				
				Param p =field.getAnnotation(Param.class);
				Object initialValue = command.getInitialValueFor(p, deviceData);
				Renderer renderer = RendererFactory.createRenderer(field,p, type, initialValue);
				paramsFrame.add(renderer);
				renderers.add(renderer);
				
				
				
				System.out.println("\t"+p.description());
				System.out.println();
			}
			if (field.isAnnotationPresent(Reading.class)){
				//todo: sensory reading
			}
				
		}
		
		this.add(paramsFrame, BorderLayout.CENTER);
		
		JPanel south = new JPanel();
		south.setLayout(new GridLayout(1, 2));
		JButton ok = new JButton("OK");
		JButton cancel = new JButton("Cancel");
		south.add(ok);
		south.add(cancel);
		
		ok.setActionCommand("ok");
		ok.addActionListener(this);

		cancel.setActionCommand("cancel");
		cancel.addActionListener(this);
		
		
		this.add(south, BorderLayout.SOUTH);
		this.setVisible(true);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		
		if (e.getActionCommand().equals("ok")){
			
			
			for (Renderer r : renderers) {
				try {
					r.getField().setAccessible(true);
					r.getField().set(command, r.getValue());
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
			Smarthouse.getInstance().sendCommand(targetDevice,command);
			this.setVisible(false);
			
		}else if (e.getActionCommand().equals("cancel")){
			System.out.println("canceled");
			this.setVisible(false);
		}
		
	}

}
